Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor builtin plugins #5261

Merged
merged 11 commits into from
Dec 23, 2024
Merged

Refactor builtin plugins #5261

merged 11 commits into from
Dec 23, 2024

Conversation

ritch
Copy link
Contributor

@ritch ritch commented Dec 11, 2024

Builtin Plugins Migration

Background

There have been several attempts to include plugins along with FiftyOne. To ensure consistency in implementation among both built-in and external plugins, we need to normalize how plugins are included in FiftyOne and FiftyOne Teams.

Current State

Currently, there is no concept of built-in plugins, only a list of BUILT_IN_OPERATORS and BUILT_IN_PANELS. These contradict the list of PluginContexts that are typically loaded for external plugins. This approach also does not support the concept of a built-in JS panel or plugin.

Changes

1. plugin_context.register(MyClass, builtin=True)

  • This approach allows us to annotate an artifact during construction and registration.
  • These parameters can be used in the future to easily reflect class metadata.

2. New fiftyone/fiftyone/builtins Directory

  • This directory would be loaded as if it were another FIFTYONE_PLUGINS_DIR.
  • Note: This will impact the behavior of the SDK and list_plugins(), as built-in plugins will be included. We can discuss how we want this to work.
  • It would mimic the structure of fiftyone-plugins/plugins, enabling a typical plugin structure and removing the need for BUILT_IN_OPERATORS and BUILT_IN_PANELS.

3. Migrate Existing Built-In Panels and Operators

  • Move existing built-in panels and operators from various areas of the codebase to the new directory.

Components to Migrate:

  • Core Operators
  • Query Performance Panel
  • Data Quality Panel
  • Model Evaluation Panel
  • Model Evaluation Operators
  • Data Lens Python Operators + Utils
  • Data Lens JS Panel (+ Registration)

Summary by CodeRabbit

  • New Features

    • Introduced new parameters to enhance operator and plugin listing functionalities, allowing users to filter built-in operators and plugins.
    • Added new classes and functions for improved operator registration and execution.
    • New YAML configuration files for both operators and panels, detailing core functionalities and available features.
    • Added built-in panels for model evaluation.
  • Documentation

    • Updated documentation for developing plugins, including enhanced examples and clearer instructions on the plugin structure and requirements.

Copy link
Contributor

coderabbitai bot commented Dec 11, 2024

Warning

Rate limit exceeded

@ritch has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 43 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6c1e301 and 4382504.

📒 Files selected for processing (4)
  • app/packages/plugins/src/index.ts (2 hunks)
  • fiftyone/plugins/constants.py (1 hunks)
  • fiftyone/plugins/core.py (4 hunks)
  • fiftyone/plugins/definitions.py (3 hunks)

Walkthrough

The pull request introduces comprehensive modifications to the FiftyOne plugin and operator management system. The changes primarily focus on enhancing the flexibility of listing and registering built-in operators and panels. A new parameter builtins_only is introduced across multiple files to allow more granular control over retrieving built-in components. The modifications span several key files in the fiftyone ecosystem, updating method signatures, registration mechanisms, and documentation to support a more dynamic approach to plugin and operator management.

Changes

File Change Summary
fiftyone/operators/registry.py Updated list_operators method and function signatures to include builtins_only parameter.
fiftyone/operators/server.py Updated get_operators function parameters for clarity and improved operator retrieval.
fiftyone/plugins/context.py Enhanced build_plugin_contexts and PluginContext.register() methods to include built-in options.
fiftyone/plugins/core.py Modified list_plugins function to support built-in plugin retrieval.
plugins/operators/__init__.py Replaced static operator list with dynamic registration function for built-in operators.
plugins/panels/__init__.py Added built-in panel registration mechanism for EvaluationPanel.
plugins/panels/fiftyone.yml Created new YAML configuration file for the @voxel51/panel plugin with metadata and built-in panel listing.
plugins/operators/fiftyone.yml Introduced new YAML configuration file for the @voxel51/operators plugin detailing core operators.
docs/source/plugins/developing_plugins.rst Updated documentation for clarity on plugin development and structure.
plugins/__init__.py Added docstring to indicate that the file contains FiftyOne built-in plugins.

Possibly related PRs

  • Adding builtin operators for more of the FO interface #4830: This PR adds builtin operators that enhance the functionality of the FiftyOne interface, which is related to the changes in the main PR that also modifies operator functionalities.
  • Add Model Evaluation Panel #5003: The introduction of the Model Evaluation Panel may connect with the changes in the main PR that involve modifying operator listing and functionality, as both enhance the user experience in managing operators.
  • Create compound group indexes by default #5174: The changes in this PR regarding the creation of compound group indexes could relate to the modifications in the main PR that involve operator management and execution, as both focus on improving the handling of operators and their contexts.
  • Allow legacy orchestration #5176: This PR's focus on allowing legacy orchestration may connect with the main PR's updates to operator execution and management, as both aim to enhance the operational capabilities of the FiftyOne framework.
  • Operator executor tests #5284: The addition of tests for the EchoOperator may relate to the changes in the main PR that involve the list_operators method, as both are concerned with ensuring the reliability and functionality of operators within the framework.
  • Merge release/v1.2.0 to develop #5302: The merge of changes from release/v1.2.0 may include enhancements that relate to the modifications in the main PR regarding operator management and functionality, as both aim to improve the overall framework.

Suggested labels

enhancement, documentation

Suggested reviewers

  • imanjra

Poem

🐰 Operators dance, plugins shine bright,
Builtins now filtered with newfound might!
Flexibility springs from each clever line,
Where code and creativity perfectly align.
A rabbit's delight in this framework so fine! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ritch ritch changed the title initial formal built ins Refactor builtin plugins Dec 11, 2024
fiftyone/plugins/core.py Outdated Show resolved Hide resolved
Copy link
Contributor Author

@ritch ritch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

fiftyone/plugins/utils.py Outdated Show resolved Hide resolved
@ritch ritch marked this pull request as ready for review December 13, 2024 16:37
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (6)
plugins/operators/__init__.py (5)

167-167: Remove unused variable sample_ids

The variable sample_ids is assigned but never used. Remove the assignment if it is unnecessary.

Apply this diff to fix the issue:

-    sample_ids = ctx.dataset.add_collection(samples, new_ids=True)
+    ctx.dataset.add_collection(samples, new_ids=True)
🧰 Tools
🪛 Ruff (0.8.2)

167-167: Local variable sample_ids is assigned to but never used

Remove assignment to unused variable sample_ids

(F841)


2039-2042: Simplify assignment with a ternary operator

The if-else block can be simplified using a ternary operator for better readability.

Apply this diff to simplify the code:

-    if curr_spaces:
-        spaces = ctx.spaces
-    else:
-        spaces = _parse_spaces(ctx, spaces)
+    spaces = ctx.spaces if curr_spaces else _parse_spaces(ctx, spaces)
🧰 Tools
🪛 Ruff (0.8.2)

2039-2042: Use ternary operator spaces = ctx.spaces if curr_spaces else _parse_spaces(ctx, spaces) instead of if-else-block

Replace if-else-block with spaces = ctx.spaces if curr_spaces else _parse_spaces(ctx, spaces)

(SIM108)


2335-2335: Iterate directly over dictionary keys

When iterating over a dictionary, you can iterate directly over the keys without calling .keys().

Apply this diff to the code:

-        for path in schema.keys()
+        for path in schema

2354-2354: Iterate directly over dictionary keys

When iterating over a dictionary, you can iterate directly over the keys without calling .keys().

Apply this diff to the code:

-        for path in schema.keys()
+        for path in schema
🧰 Tools
🪛 Ruff (0.8.2)

2354-2354: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


202-290: Reduce code duplication in input helper functions

The functions _clone_sample_field_inputs and _clone_frame_field_inputs have similar logic. Consider refactoring to extract common code into a shared helper function to improve maintainability and reduce duplication.

Also applies to: 321-418

fiftyone/plugins/core.py (1)

495-505: Consider enhancing error handling for built-in plugin loading.

While the implementation correctly handles both external and built-in plugins, consider adding specific error logging for built-in plugin failures to help with debugging.

 def _list_plugins(enabled=None, include_builtin=False):
     plugins = []
     external_plugin_paths = list(_iter_plugin_metadata_files())
     builtin_plugin_paths = list(
         _iter_plugin_metadata_files(BUILTIN_PLUGINS_DIR)
     )
+    if include_builtin and not builtin_plugin_paths:
+        logger.debug("No built-in plugins found in %s", BUILTIN_PLUGINS_DIR)
+
     all_plugin_paths = (
         (external_plugin_paths + builtin_plugin_paths)
         if include_builtin
         else external_plugin_paths
     )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6766a55 and dc182ac.

📒 Files selected for processing (7)
  • fiftyone/operators/registry.py (4 hunks)
  • fiftyone/operators/server.py (1 hunks)
  • fiftyone/plugins/context.py (2 hunks)
  • fiftyone/plugins/core.py (4 hunks)
  • plugins/__init__.py (1 hunks)
  • plugins/operators/__init__.py (1 hunks)
  • plugins/operators/fiftyone.yml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • plugins/init.py
🧰 Additional context used
🪛 Ruff (0.8.2)
fiftyone/operators/registry.py

52-52: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)

plugins/operators/__init__.py

118-118: Do not use bare except

(E722)


167-167: Local variable sample_ids is assigned to but never used

Remove assignment to unused variable sample_ids

(F841)


2039-2042: Use ternary operator spaces = ctx.spaces if curr_spaces else _parse_spaces(ctx, spaces) instead of if-else-block

Replace if-else-block with spaces = ctx.spaces if curr_spaces else _parse_spaces(ctx, spaces)

(SIM108)


2336-2336: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


2354-2354: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (7)
fiftyone/plugins/context.py (2)

38-38: Include built-in plugins in plugin contexts

The addition of include_builtin=True correctly includes built-in plugins in the plugin contexts.


99-103: Update register method to accept builtin parameter

The register method now accepts a builtin parameter, and the instance initialization correctly passes _builtin=builtin. This enhancement allows for proper identification of built-in plugins.

fiftyone/operators/registry.py (2)

51-55: Enhance operator filtering with builtins_only parameter

The addition of the builtins_only parameter provides more granular control over operator listing in the list_operators function.

🧰 Tools
🪛 Ruff (0.8.2)

52-52: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)


Line range hint 83-105: Implement builtins_only parameter in operator registry

The list_operators method correctly handles the include_builtin and builtins_only parameters to filter operators as intended.

fiftyone/operators/server.py (1)

30-31: LGTM! Parameter naming improvement enhances clarity.

The explicit parameter name include_builtin=True better communicates the intent compared to the previous boolean literal.

fiftyone/plugins/core.py (2)

31-33: LGTM! Well-structured path construction.

The BUILTIN_PLUGINS_DIR constant is correctly defined using os.path.join for cross-platform compatibility.


54-60: LGTM! Good backward compatibility consideration.

The include_builtin=False default value ensures backward compatibility with existing code while providing the option to include built-in plugins when needed.

plugins/operators/__init__.py Outdated Show resolved Hide resolved
version: 1.0.0
fiftyone:
version: "*"
url: https://github.com/voxel51/fiftyone/fiftyone/builtins/operators
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the plugin URL

The URL in the plugin definition appears to have a duplicate 'fiftyone' in the path. Update the URL to point to the correct location.

Apply this diff to fix the URL:

- url: https://github.com/voxel51/fiftyone/fiftyone/builtins/operators
+ url: https://github.com/voxel51/fiftyone/tree/main/fiftyone/builtins/operators
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
url: https://github.com/voxel51/fiftyone/fiftyone/builtins/operators
url: https://github.com/voxel51/fiftyone/tree/main/fiftyone/builtins/operators

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc182ac and 8074f54.

📒 Files selected for processing (4)
  • docs/source/plugins/developing_plugins.rst (1 hunks)
  • fiftyone/operators/registry.py (4 hunks)
  • plugins/operators/__init__.py (3 hunks)
  • plugins/operators/foo.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • plugins/operators/foo.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/operators/init.py
🧰 Additional context used
🪛 Ruff (0.8.2)
fiftyone/operators/registry.py

50-50: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)

🔇 Additional comments (3)
fiftyone/operators/registry.py (2)

Line range hint 81-103: LGTM! Clean implementation of built-in operator filtering

The implementation efficiently handles the filtering of built-in operators using clear and maintainable list comprehensions.


137-137: LGTM! Explicit inclusion of built-in operators

The explicit include_builtin=True parameter ensures that operator existence checks consider all operators, including built-ins.

docs/source/plugins/developing_plugins.rst (1)

89-89: LGTM! Documentation path update

The path to the built-in operators module has been correctly updated to reflect the current codebase structure.

fiftyone/operators/registry.py Show resolved Hide resolved
Copy link
Contributor

@imanjra imanjra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to extend this in a few to bring back the model eval panel

plugins/operators/__init__.py Outdated Show resolved Hide resolved
plugins/operators/foo.py Outdated Show resolved Hide resolved
Copy link
Contributor

@imanjra imanjra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally. Works great. LGTM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
plugins/operators/__init__.py (2)

2374-2406: Add docstring documentation to the register function

The new register() function should include docstring documentation explaining its purpose, parameters, and usage.

Add this docstring:

 def register(p):
+    """Register built-in operators with the plugin system.
+    
+    Args:
+        p: The plugin context to register operators with
+    """
     p.register(EditFieldInfo, builtin=True)

2374-2374: Add type hint for the register function parameter

Add a type hint to improve code clarity and enable better IDE support.

-def register(p):
+def register(p: "PluginContext") -> None:

Note: Add the following import at the top of the file:

from fiftyone.plugins.context import PluginContext
plugins/panels/fiftyone.yml (1)

6-6: Update the repository URL

The current URL points to a subdirectory in the main repository. Consider updating it to point to the actual plugin documentation or a more specific location.

-url: https://github.com/voxel51/fiftyone/plugins/panels
+url: https://github.com/voxel51/fiftyone/tree/main/plugins/panels
plugins/panels/__init__.py (2)

1-7: Enhance module documentation

The module docstring could be more descriptive about its purpose and functionality. Consider adding:

  • Description of what built-in panels are
  • How to register new built-in panels
  • Example usage
 """
 Builtin panels.
+
+Built-in panels are core components of FiftyOne that provide essential
+functionality. This module handles the registration of built-in panels
+using the plugin system.
+
+Example:
+    To register a new built-in panel:
+
+    ```python
+    from fiftyone.plugins import get_plugin_context
+    
+    p = get_plugin_context()
+    p.register(MyPanel, builtin=True)
+    ```
 
 | Copyright 2017-2024, Voxel51, Inc.
 | `voxel51.com <https://voxel51.com/>`_
 |
 """

12-13: Add error handling and type hints to register function

The registration function could benefit from:

  • Type hints for better code maintainability
  • Error handling for registration failures
  • Documentation string
-def register(p):
-    p.register(EvaluationPanel, builtin=True)
+from typing import Any
+from fiftyone.plugins.context import PluginContext
+
+def register(p: PluginContext) -> None:
+    """Register built-in panels with the plugin system.
+
+    Args:
+        p: The plugin context to register panels with
+
+    Raises:
+        ValueError: If registration fails
+    """
+    try:
+        p.register(EvaluationPanel, builtin=True)
+    except Exception as e:
+        raise ValueError(f"Failed to register built-in panel: {e}")
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8074f54 and 373eb0f.

📒 Files selected for processing (3)
  • plugins/operators/__init__.py (2 hunks)
  • plugins/panels/__init__.py (1 hunks)
  • plugins/panels/fiftyone.yml (1 hunks)
🔇 Additional comments (3)
plugins/operators/__init__.py (1)

Line range hint 118-118: Specify exception type instead of bare 'except'

The previous review comment about replacing the bare except with except json.JSONDecodeError: is still valid.

plugins/panels/fiftyone.yml (2)

7-8: Verify panel naming consistency

The panel name model_evaluation_panel_builtin differs from the class name EvaluationPanel in __init__.py. Please verify if this naming inconsistency is intentional or needs alignment.

✅ Verification successful

Panel naming is consistent with implementation

The naming is intentionally different and correct. The store name model_evaluation_panel_builtin in model_evaluation.py is used as an internal identifier, while EvaluationPanel is the class name. This is a common pattern where internal identifiers are more descriptive and follow a different naming convention than class names.

Evidence from the codebase:

  • model_evaluation.py explicitly defines STORE_NAME = "model_evaluation_panel_builtin"
  • The panel is properly registered as a builtin panel using the EvaluationPanel class
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to both names to ensure consistency
rg "model_evaluation_panel_builtin|EvaluationPanel" --type py

Length of output: 355


5-5: Consider specifying a minimum FiftyOne version requirement

Using "*" for version compatibility might be too permissive and could lead to compatibility issues. Consider specifying a minimum version requirement (e.g., ">=1.0.0") to ensure the plugin works with compatible FiftyOne versions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
plugins/operators/__init__.py (1)

2374-2406: LGTM! Well-structured registration of built-in operators

The implementation successfully achieves the PR's objective of standardizing built-in plugin registration. The operators are logically grouped and consistently registered with the builtin=True flag.

Consider adding a docstring to the register function explaining its purpose and the significance of the builtin=True flag for future maintainers. This would help document the architectural decision to standardize built-in plugin registration.

Example:

def register(p):
    """Register built-in operators with the plugin system.
    
    This function implements the standardized method for registering built-in
    operators, ensuring consistency with the plugin architecture.
    
    Args:
        p: The plugin context to register operators with
    """
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 373eb0f and bfb596a.

📒 Files selected for processing (10)
  • docs/source/plugins/developing_plugins.rst (1 hunks)
  • fiftyone/operators/registry.py (4 hunks)
  • fiftyone/operators/server.py (1 hunks)
  • fiftyone/plugins/context.py (2 hunks)
  • fiftyone/plugins/core.py (4 hunks)
  • plugins/__init__.py (1 hunks)
  • plugins/operators/__init__.py (2 hunks)
  • plugins/operators/fiftyone.yml (1 hunks)
  • plugins/panels/__init__.py (1 hunks)
  • plugins/panels/fiftyone.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • plugins/init.py
  • plugins/panels/init.py
  • plugins/panels/fiftyone.yml
  • fiftyone/plugins/context.py
  • fiftyone/operators/server.py
  • docs/source/plugins/developing_plugins.rst
🧰 Additional context used
🪛 Ruff (0.8.2)
fiftyone/operators/registry.py

50-50: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)

🔇 Additional comments (8)
plugins/operators/fiftyone.yml (3)

6-6: Fix the repository URL path

The URL contains a duplicate 'fiftyone' in the path which should be removed.


8-39: LGTM! Comprehensive operator coverage

The list of operators provides good coverage for essential operations including field management, view/workspace operations, and group management.


3-5: Consider specifying a compatible FiftyOne version range

The wildcard version ("*") might be too permissive. Consider specifying a version range that matches the minimum required FiftyOne version for these operators.

fiftyone/operators/registry.py (2)

50-50: Simplify the boolean comparison

Replace the inequality comparison with a direct boolean check for better readability.

🧰 Tools
🪛 Ruff (0.8.2)

50-50: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)


99-103: LGTM! Clear filtering logic for built-in operators

The implementation correctly filters operators based on the include_builtin and builtins_only flags.

fiftyone/plugins/core.py (2)

31-33: LGTM! Clear path definition for built-in plugins

The path construction for built-in plugins directory is correct and follows the package structure.


495-505: LGTM! Well-structured plugin listing implementation

The implementation correctly handles both external and built-in plugins while maintaining proper error handling. The separation of plugin paths and conditional inclusion based on the include_builtin flag is clean and maintainable.

plugins/operators/__init__.py (1)

Line range hint 118-118: Specify exception type instead of bare 'except'

The previous review comment about specifying json.JSONDecodeError instead of using a bare except is still valid.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
plugins/operators/__init__.py (2)

2373-2405: Add docstring documentation for the register function

The register function should include a docstring explaining its purpose and parameters.

Apply this diff to add documentation:

 def register(p):
+    """Register all built-in operators with the plugin system.
+
+    Args:
+        p: The plugin context to register operators with
+    """
     p.register(EditFieldInfo, builtin=True)
     p.register(CloneSelectedSamples, builtin=True)

2373-2405: Consider grouping operator registrations by functionality

The operator registrations could be organized into logical groups with comments to improve readability and maintainability.

Apply this diff to group the registrations:

 def register(p):
+    # Field operations
     p.register(EditFieldInfo, builtin=True)
     p.register(CloneSampleField, builtin=True)
     p.register(CloneFrameField, builtin=True)
     p.register(RenameSampleField, builtin=True)
     p.register(RenameFrameField, builtin=True)
     p.register(ClearSampleField, builtin=True)
     p.register(ClearFrameField, builtin=True)
     p.register(DeleteSampleField, builtin=True)
     p.register(DeleteFrameField, builtin=True)
 
+    # Sample operations
     p.register(CloneSelectedSamples, builtin=True)
     p.register(DeleteSelectedSamples, builtin=True)
     p.register(DeleteSelectedLabels, builtin=True)
 
+    # Index operations
     p.register(CreateIndex, builtin=True)
     p.register(DropIndex, builtin=True)
 
+    # Summary operations
     p.register(CreateSummaryField, builtin=True)
     p.register(UpdateSummaryField, builtin=True)
     p.register(DeleteSummaryField, builtin=True)
 
+    # Group operations
     p.register(AddGroupSlice, builtin=True)
     p.register(RenameGroupSlice, builtin=True)
     p.register(DeleteGroupSlice, builtin=True)
 
+    # View operations
     p.register(ListSavedViews, builtin=True)
     p.register(LoadSavedView, builtin=True)
     p.register(SaveView, builtin=True)
     p.register(EditSavedViewInfo, builtin=True)
     p.register(DeleteSavedView, builtin=True)
 
+    # Workspace operations
     p.register(ListWorkspaces, builtin=True)
     p.register(LoadWorkspace, builtin=True)
     p.register(SaveWorkspace, builtin=True)
     p.register(EditWorkspaceInfo, builtin=True)
     p.register(DeleteWorkspace, builtin=True)
 
+    # Utility operations
     p.register(SyncLastModifiedAt, builtin=True)
     p.register(ListFiles, builtin=True)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfb596a and 146ce28.

📒 Files selected for processing (1)
  • plugins/operators/__init__.py (1 hunks)
🔇 Additional comments (1)
plugins/operators/__init__.py (1)

Line range hint 118-118: Specify exception type instead of bare 'except'

Using a bare except: statement can catch unexpected exceptions. Specify the exception type to handle only the intended exceptions.

- save_workspace
- edit_workspace_info
- delete_workspace
- sync_last_modified_at
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have the list pretty much here so it wouldn’t be much of a change to reference the list instead of the operator itself but would prevent people from saving their own as builtin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only part of this list this needs to support...in teams we have the other built-ins.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/unittests/operators/executor_tests.py (1)

34-34: Confirm the long-term plan for registering built-in operators.
Appending to the internal “_EXTRA_OPERATORS” list works for this test scenario; however, consider providing a dedicated method like "register_builtin" to maintain clarity and ensure consistent usage across the codebase.

fiftyone/operators/registry.py (1)

105-106: Clarify interplay between “include_builtin” and “builtins_only”.
When “builtins_only” is True, “include_builtin” becomes irrelevant. Consider making them mutually exclusive or documenting their intended interplay to avoid confusion.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 146ce28 and 108e009.

📒 Files selected for processing (2)
  • fiftyone/operators/registry.py (4 hunks)
  • tests/unittests/operators/executor_tests.py (2 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
fiftyone/operators/registry.py

50-50: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)

🔇 Additional comments (3)
tests/unittests/operators/executor_tests.py (1)

13-13: Import alignment looks good!
This line properly switches from the old builtin-based import to the new registry-based approach, which aligns with the refactored plugin architecture.

fiftyone/operators/registry.py (2)

35-35: New parameter addition is consistent with the PR objectives.
The introduction of “builtins_only” is coherent with the enhanced plugin filtering logic.


49-50: Use a direct boolean check instead of “enabled != False”.
This comment mirrors a recommendation from a previous review about avoiding inequality comparisons to False.

-        include_builtin=enabled != False,
+        include_builtin=bool(enabled),
🧰 Tools
🪛 Ruff (0.8.2)

50-50: Avoid inequality comparisons to False; use if enabled: for truth checks

Replace with enabled

(E712)

fiftyone/operators/registry.py Outdated Show resolved Hide resolved
"""
try:
instance = cls()
instance = cls(_builtin=builtin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unnecessary to expose since you have BUILTIN_PLUGINS_DIR defined and iterate through that.

fiftyone/plugins/core.py Show resolved Hide resolved
Copy link
Contributor

@kaixi-wang kaixi-wang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just note that this makes it easy to for non-builtins to be marked as builtin, which could lead to problems

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/operators/__init__.py (1)

2373-2405: Streamline operator registration.

The repeated register calls could be reduced by collecting all operator classes in a single list and iterating over them, making the code more concise and easier to maintain.

Suggested refactor:

 def register(p):
-    p.register(EditFieldInfo)
-    p.register(CloneSelectedSamples)
-    p.register(CloneSampleField)
-    ...
-    p.register(ListFiles)
+    operators = [
+        EditFieldInfo,
+        CloneSelectedSamples,
+        CloneSampleField,
+        CloneFrameField,
+        RenameSampleField,
+        ...,
+        ListFiles,
+    ]
+    for op in operators:
+        p.register(op)
🛑 Comments failed to post (1)
fiftyone/plugins/definitions.py (1)

44-48: ⚠️ Potential issue

Add a missing return statement.

The builtin property currently does not return any value, which means it always evaluates to None. A return statement is needed to return the boolean result of directory matching.

Possible fix:

 @property
 def builtin(self):
     """Whether the plugin is a builtin plugin."""
-    self.directory.startswith(BUILTIN_PLUGINS_DIR)
+    return self.directory.startswith(BUILTIN_PLUGINS_DIR)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    @property
    def builtin(self):
        """Whether the plugin is a builtin plugin."""
        return self.directory.startswith(BUILTIN_PLUGINS_DIR)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
plugins/operators/__init__.py (2)

2373-2405: Consider grouping operator registrations by functionality

The register function provides a good centralized location for operator registration, but it could be better organized. Consider grouping related operators together with comments indicating their purpose.

Apply this diff to improve organization:

 def register(p):
+    # Field operations
     p.register(EditFieldInfo)
     p.register(CloneSelectedSamples)
     p.register(CloneSampleField)
     p.register(CloneFrameField)
     p.register(RenameSampleField)
     p.register(RenameFrameField)
     p.register(ClearSampleField)
     p.register(ClearFrameField)
     p.register(DeleteSampleField)
     p.register(DeleteFrameField)
 
+    # Sample and label operations
     p.register(DeleteSelectedSamples)
     p.register(DeleteSelectedLabels)
 
+    # Index operations
     p.register(CreateIndex)
     p.register(DropIndex)
 
+    # Summary field operations
     p.register(CreateSummaryField)
     p.register(UpdateSummaryField)
     p.register(DeleteSummaryField)
 
+    # Group operations
     p.register(AddGroupSlice)
     p.register(RenameGroupSlice)
     p.register(DeleteGroupSlice)
 
+    # View operations
     p.register(ListSavedViews)
     p.register(LoadSavedView)
     p.register(SaveView)
     p.register(EditSavedViewInfo)
     p.register(DeleteSavedView)
 
+    # Workspace operations
     p.register(ListWorkspaces)
     p.register(LoadWorkspace)
     p.register(SaveWorkspace)
     p.register(EditWorkspaceInfo)
     p.register(DeleteWorkspace)
 
+    # Utility operations
     p.register(SyncLastModifiedAt)
     p.register(ListFiles)

Line range hint 1-2405: Consider splitting operators into separate modules

The current file is quite large and handles multiple types of operations. This can make maintenance, testing, and code navigation more challenging.

Consider reorganizing the code into separate modules:

  1. Create a operators/ subdirectory
  2. Split operators into logical groups in separate files:
    • field_operators.py for field-related operations
    • sample_operators.py for sample operations
    • view_operators.py for view operations
    • workspace_operators.py for workspace operations
    • etc.
  3. Create a central registry.py that imports and registers all operators
  4. Move utility functions to a separate utils.py module

This would improve:

  • Code organization and maintainability
  • Testing isolation
  • Code navigation and readability
  • Module cohesion
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2a3c08 and 6c1e301.

📒 Files selected for processing (4)
  • fiftyone/plugins/context.py (2 hunks)
  • fiftyone/plugins/definitions.py (1 hunks)
  • plugins/operators/__init__.py (1 hunks)
  • plugins/panels/__init__.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • fiftyone/plugins/definitions.py
  • plugins/panels/init.py
  • fiftyone/plugins/context.py
🔇 Additional comments (1)
plugins/operators/__init__.py (1)

Line range hint 1018-1018: Specify exception type instead of bare 'except'

A previous review has already identified this issue. The bare except block should be replaced with a specific exception type.

Copy link
Contributor

@kaixi-wang kaixi-wang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm thanks!

@ritch
Copy link
Contributor Author

ritch commented Dec 23, 2024

just note that this makes it easy to for non-builtins to be marked as builtin, which could lead to problems
Resolve this by only resolving builtin based on path.

Now all plugins (including JS) are aware of being builtin, and its all based on one way of defining a plugin: the PluginDefinition / fiftyone.yml. Builtin is now determined based on where this file is. If its in the expected builtin plugin directory then it is considered a builtin plugin.

@ritch ritch requested a review from kaixi-wang December 23, 2024 18:53
@ritch ritch enabled auto-merge December 23, 2024 19:29
@ritch ritch merged commit 766e644 into develop Dec 23, 2024
14 checks passed
@ritch ritch deleted the builtins branch December 23, 2024 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants